package com.ly.spring.aop.proxy;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Company 源辰信息
 *
 * @author navy
 * @date 2024/11/7
 * Email haijunzhou@hnit.edu.cn
 */
public class ProxyDemo {

    public static void main(String[] args) {
        人 zhangsan = new 房东();
        人 lisi = new 中介();
        人 zhaoliu = new 中介2();
        // 代理
        ((中介)lisi).person = zhangsan;
        lisi.say();
        System.out.println("-----------------------------");
        zhaoliu.say();
        System.out.println("-----------------------------");
        人 wangwu = jdkProxy(zhangsan);
        wangwu.say();
        System.out.println("-----------------------------");
        人 abc = cglibProxy(zhangsan);
        abc.say();
    }

    // 基于接口实现的动态代理, 由JDK提供的方法
    public static <T> T jdkProxy(T t){
        return (T)Proxy.newProxyInstance(
                t.getClass().getClassLoader(),
                t.getClass().getInterfaces(),
                (proxy, method, args) -> {
                    // proxy 代理对象
                    // method 拦截的方法
                    // args 方法的参数
                    if(method.getName().equals("say")){
                        System.out.println("急需出租");
                        Object ret = method.invoke(t, args);
                        System.out.println("交通便利,购物方便...");
                        return ret;
                    }
                    return null;
                }
        );
    }

    // 基于继承的动态代理, CGLIB(动态字节码) 提供的方法
    public static <T> T cglibProxy(T t){
        Enhancer enhancer = new Enhancer();
        // 设置父类
        enhancer.setSuperclass(t.getClass());
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o,
                                    Method method,
                                    Object[] objects,
                                    MethodProxy methodProxy) throws Throwable {
                // o 代理对象 , method 方法, objects 参数, methodProxy 方法代理对象
                if(method.getName().equals("say")){
                    System.out.println("急需出租");
                    Object ret = methodProxy.invoke(t, objects);
                    System.out.println("交通便利,购物方便...");
                    return ret;
                }
                return null;
            }
        });
        return (T) enhancer.create();
    }


}

// 抽象主题
interface 人 {
    void say();
}

// 真实主题
class 房东 implements 人 {
    @Override
    public void say() {
        System.out.println("我有一套好房");
    }
}

// 代理主题
class 中介 implements 人 {

    人 person;

    @Override
    public void say() {
        System.out.println("急需出租");
        person.say();
        System.out.println("交通便利,购物方便...");
    }
}

// 基于继承实现
class 中介2 extends 房东 {
    @Override
    public void say() {
        System.out.println("急需出租");
        super.say();
        System.out.println("交通便利,购物方便...");
    }
}

/**
 * 题目: 请定义 被告 和 律师 的代理关系
 */